package com.gzceb.zhgjj.security.dao;

// default package

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.LockMode;
import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.Session;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.context.ApplicationContext;

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import org.springframework.orm.hibernate3.HibernateCallback;

import org.springframework.security.authentication.encoding.PasswordEncoder;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;

import com.gzceb.zhgjj.security.entity.*;
import com.gzceb.zhgjj.util.Utils;

/**
 * A data access object (DAO) providing persistence and search support for
 * SysUsers entities. Transaction control of the save(), update() and delete()
 * operations can directly support Spring container-managed transactions or they
 * can be augmented to handle user-managed Spring transactions. Each of these
 * methods provides additional information for how to configure it for the
 * desired type of transaction control.
 * 
 * @see .SysUsers
 * @author MyEclipse Persistence Tools
 */

public class SysUsersDAO extends HibernateDaoSupport {
	private static final Logger log = LoggerFactory
			.getLogger(SysUsersDAO.class);
	// property constants
	public static final String USER_ACCOUNT = "userAccount";
	public static final String USER_NAME = "userName";
	public static final String USER_PASSWORD = "userPassword";
	public static final String USER_DESC = "userDesc";
	public static final String ENABLED = "enabled";
	public static final String ISSYS = "issys";
	public static final String USER_DEPT = "userDept";
	public static final String USER_DUTY = "userDuty";
	public static final String SUB_SYSTEM = "subSystem";

	// 对用户输入的密码进行MD5编码
	private PasswordEncoder passwordEncoder;

	// 通过SysrolesDao获得角色实例。
	private SysRolesDAO sysRolesDAO;

	protected void initDao() {
		// do nothing
	}

	// 注入sysRolesDao
	public void setSysRolesDAO(SysRolesDAO sysRolesDAO) {
		this.sysRolesDAO = sysRolesDAO;
	}

	public SysRolesDAO getSysRolesDAO() {
		return this.sysRolesDAO;
	}

	// 注入密码MD5编码
	public void setPasswordEncoder(PasswordEncoder passwordEncoder) {
		this.passwordEncoder = passwordEncoder;
	}

	public PasswordEncoder getPasswordEncoder() {
		return this.passwordEncoder;
	}

	@SuppressWarnings("null")
	public void persist(SysUsers transientInstance, String[] rolesArr) {
		log.debug("持久化一个用户实例！");
		try {
			// 先将该用户对应的所有角色
			Set<SysUsersRoles> userRoles = new HashSet<SysUsersRoles>();

			// 角色实例
			SysRoles role = null;

			for (String roleId : rolesArr) {

				if (null != roleId && !"".equals(roleId)) {

					role = sysRolesDAO.findById(roleId);

					SysUsersRoles userRole = new SysUsersRoles(Utils.getPkId(),
							transientInstance, role, true);

					userRoles.add(userRole);
				}

			}

			transientInstance.setUserId(Utils.getPkId() + "");

			// 密码通过盐值加密以备存储入数据库
			String newPassword = passwordEncoder.encodePassword(
					transientInstance.getUserPassword().trim(),
					transientInstance.getUserName().trim());

			transientInstance.setUserPassword(newPassword);

			if (null != userRoles)
				transientInstance.setSysUsersRoleses(userRoles);

			getHibernateTemplate().persist(transientInstance);

			log.debug("持久化实例成功！");
		} catch (RuntimeException re) {
			log.error("持久化用户实例失败！", re);
			throw re;
		}
	}

	public void save(SysUsers transientInstance) {
		log.debug("saving SysUsers instance");
		try {
			getHibernateTemplate().save(transientInstance);
			log.debug("save successful");
		} catch (RuntimeException re) {
			log.error("save failed", re);
			throw re;
		}
	}

	public void delete(SysUsers persistentInstance) {
		log.debug("deleting SysUsers instance");
		try {
			getHibernateTemplate().delete(persistentInstance);
			log.debug("delete successful");
		} catch (RuntimeException re) {
			log.error("delete failed", re);
			throw re;
		}
	}

	/**
	 * 删除用户。
	 * 
	 * 该方法设置用户的 enable 字段，逻辑上删除用户。
	 * 
	 * @param userId
	 *            用户ID值
	 * @return 无
	 * @throws RuntimeException
	 *             当查询、删除时都可能引发此异常
	 */
	public void delete(String userId) {
		log.debug("根据一个用户id删除一个用户，角色id为：" + userId);
		try {
			SysUsers user = findById(userId);
			user.setEnabled(false);
			getHibernateTemplate().saveOrUpdate(user);
			log.debug("删除成功。");
		} catch (RuntimeException re) {
			log.error("删除失败。", re);
			throw re;
		}
	}

	public SysUsers findById(java.lang.String id) {
		log.debug("getting SysUsers instance with id: " + id);
		try {
			SysUsers instance = (SysUsers) getHibernateTemplate().get(
					"SysUsers", id);
			return instance;
		} catch (RuntimeException re) {
			log.error("get failed", re);
			throw re;
		}
	}

	public List findByExample(SysUsers instance) {
		log.debug("finding SysUsers instance by example");
		try {
			List results = getHibernateTemplate().findByExample(instance);
			log.debug("find by example successful, result size: "
					+ results.size());
			return results;
		} catch (RuntimeException re) {
			log.error("find by example failed", re);
			throw re;
		}
	}

	public List findByProperty(String propertyName, Object value) {
		log.debug("finding SysUsers instance with property: " + propertyName
				+ ", value: " + value);
		try {
			String queryString = "from SysUsers as model where model."
					+ propertyName + "= ?";
			return getHibernateTemplate().find(queryString, value);
		} catch (RuntimeException re) {
			log.error("find by property name failed", re);
			throw re;
		}
	}

	public List findByUserAccount(Object userAccount) {
		return findByProperty(USER_ACCOUNT, userAccount);
	}

	/**
	 * 根据用户账号反馈SysUsers实例对象。
	 * 
	 * 用户账号即员工工号，唯一
	 * 
	 * @param userAccount
	 *            用户账号值
	 * @return SysUsers实例
	 * @throws RuntimeException
	 *             当查询时都可能引发此异常
	 */

	public SysUsers findByUserAccount(String userAccount) {
		log.debug("根据UserAccount查找SysUsers实例对象: " + userAccount);
		try {
			SysUsers instance = (SysUsers) getHibernateTemplate().find(
					"from SysUsers where user_account='" + userAccount + "'")
					.get(0);
			if (instance == null) {
				log.debug("没有相匹配的SysUsers实例对象！");
				instance = new SysUsers();
			} else {
				log.debug("相匹配的SysUsers实例对象被找到！");
			}
			return instance;
		} catch (RuntimeException re) {
			log.error("使用userAccount字符串查找SysUsers实例对象失败。");
			throw re;
		}
	}

	public List findByUserName(Object userName) {
		return findByProperty(USER_NAME, userName);
	}

	public List findByUserPassword(Object userPassword) {
		return findByProperty(USER_PASSWORD, userPassword);
	}

	public List findByUserDesc(Object userDesc) {
		return findByProperty(USER_DESC, userDesc);
	}

	public List findByEnabled(Object enabled) {
		return findByProperty(ENABLED, enabled);
	}

	public List findByIssys(Object issys) {
		return findByProperty(ISSYS, issys);
	}

	public List findByUserDept(Object userDept) {
		return findByProperty(USER_DEPT, userDept);
	}

	public List findByUserDuty(Object userDuty) {
		return findByProperty(USER_DUTY, userDuty);
	}

	public List findBySubSystem(Object subSystem) {
		return findByProperty(SUB_SYSTEM, subSystem);
	}

	public List findAll() {
		log.debug("finding all SysUsers instances");
		try {
			String queryString = "from SysUsers";
			return getHibernateTemplate().find(queryString);
		} catch (RuntimeException re) {
			log.error("find all failed", re);
			throw re;
		}
	}

	/**
	 * 获取用户SysUsers对象列表。
	 * 
	 * 通过用户的姓名、账号、所在单位等信息查询
	 * 
	 * @param qryUnit
	 *            String 用户单位
	 * @param qryUserAccount
	 *            String 用户账户
	 * @param qryUsername
	 *            String 用户姓名
	 * @param qryModule
	 *            String 用户所在模块
	 * @param qryRole
	 *            String 用户相关的角色
	 * @return SysUsers实例列表
	 * @throws RuntimeException
	 *             当查询时都可能引发此异常
	 */
	public List<SysUsers> findUserLst(String qryUnit, String qryUserAccount,
			String qryUsername, String qryModule, String qryRole) {
		log.debug("根据用户姓名、账户等字段查找用户列表");

		List<SysUsers> list = null;
		String sql = "select users from SysUsers users where users.enabled = 1 ";
		// 查询与用户相关联的角色列表。
		if (null != qryRole && !"".equals(qryRole)) {
			sql = "select users from SysUsers users, SysUsersRoles usersRoles "
					+ "where users.user_id = usersRoles.user_id and users.enabled = 1 ";
		}
		try {

			if (null != qryUnit && !"".equals(qryUnit)) {
				sql += "and users.user_dept='" + qryUnit + "' ";
			}

			if (null != qryUserAccount && !"".equals(qryUserAccount)) {
				sql += "and users.user_account='" + qryUserAccount + "' ";
			}

			if (null != qryUsername && !"".equals(qryUsername)) {
				sql += "and users.user_name = '" + qryUsername + "' ";
			}

			if (null != qryModule && !"".equals(qryModule)
					&& !"00".equals(qryModule)) {
				sql += "and users.sub_system='" + qryModule + "' ";
			}

			if (null != qryRole && !"".equals(qryRole) && !"00".equals(qryRole)) {
				sql += "and usersRoles.role_id ='" + qryRole + "'";
			}

			list = getHibernateTemplate().find(sql);

			return list;
		} catch (RuntimeException re) {
			log.error("findUserLst() 错误！", re);
			throw re;
		}
	}

	/**
	 * 获取用户拥有的授权列表。
	 * 
	 * 通过用户的姓名信息查询
	 * 
	 * @param username
	 *            String 用户名称
	 * 
	 * @return GrantedAuthority实例列表
	 * @throws RuntimeException
	 *             当查询时都可能引发此异常
	 */
	public List<GrantedAuthority> loadUserAuthoritiesByName(String username) {

		try {

			List<GrantedAuthority> auths = new ArrayList<GrantedAuthority>();

			List<String> query1 = loadUserAuthorities(username);

			for (String roleName : query1) {
				SimpleGrantedAuthority authority = new SimpleGrantedAuthority(
						roleName);
				auths.add(authority);
			}

			return auths;

		} catch (RuntimeException re) {
			log.error("find by authorities by username failed.", re);
			throw re;
		}
	}

	/**
	 * 获取用户拥有的授权名称列表。
	 * 
	 * 通过用户的姓名信息查询
	 * 
	 * @param username
	 *            String 用户名称
	 * 
	 * @return 授权名称String列表
	 * @throws RuntimeException
	 *             当查询时都可能引发此异常
	 */
	public List<String> loadUserAuthorities(final String username) {

		try {

			return getHibernateTemplate().executeFind(new HibernateCallback() {
				public List<SysAuthorities> doInHibernate(Session session)
						throws HibernateException, SQLException {
					Query query = session
							.createSQLQuery("select a.authority_name "
									+ "from sys_authorities a, sys_roles_authorities b, sys_users_roles c, sys_users d "
									+ "where   a.authority_id = b.authority_id and b.role_id = c.role_id  "
									+ "and c.user_id = d.user_id and  d.user_account = '"
									+ username + "'");

					return query.list();
				}
			});

		} catch (RuntimeException re) {
			log.error("find by authorities by username failed.", re);
			throw re;
		}
	}

	public SysUsers merge(SysUsers detachedInstance) {
		log.debug("merging SysUsers instance");
		try {
			SysUsers result = (SysUsers) getHibernateTemplate().merge(
					detachedInstance);
			log.debug("merge successful");
			return result;
		} catch (RuntimeException re) {
			log.error("merge failed", re);
			throw re;
		}
	}

	public void attachDirty(SysUsers instance) {
		log.debug("attaching dirty SysUsers instance");
		try {
			getHibernateTemplate().saveOrUpdate(instance);
			log.debug("attach successful");
		} catch (RuntimeException re) {
			log.error("attach failed", re);
			throw re;
		}
	}

	/**
	 * 保存用户，重载attachDirty。
	 * 
	 * 保存或更新一个用户实例，并且保存用户和角色之间的关联关系。
	 * 
	 * @param instance
	 *            用户实例
	 * @param rolesArr
	 *            用户角色字段数组
	 * @param tempPassword
	 * @return 无
	 * @throws RuntimeException
	 *             当查询、删除时都可能引发此异常
	 */
	public void attachDirty(SysUsers instance, String[] rolesArr,
			String tempPassword) {
		log.debug("更新一个用户实例");
		try {
			// 先将该用户对应的所有角色
			Set<SysUsersRoles> userRoles = new HashSet<SysUsersRoles>();

			// 角色实例
			SysRoles role = new SysRoles();
			for (String roleId : rolesArr) {
				if (null != roleId && !"".equals(roleId)) {
					role = sysRolesDAO.findById(roleId);
					userRoles.add((SysUsersRoles) new SysUsersRoles(Utils
							.getPkId(), instance, role, true));
				}

			}
			if (tempPassword.equals(instance.getUserPassword())) {

				// 密码通过盐值加密以备存储入数据库
				String newPassword = passwordEncoder.encodePassword(instance
						.getUserPassword().trim(), instance.getUserName()
						.trim());

				instance.setUserPassword(newPassword);
			}

			if (null != userRoles)
				instance.setSysUsersRoleses(userRoles);

			getHibernateTemplate().saveOrUpdate(instance);

			log.debug("更新用户实例成功！");

		} catch (RuntimeException re) {
			log.error("更新用户实例失败");
			throw re;
		}

	}

	public void attachClean(SysUsers instance) {
		log.debug("attaching clean SysUsers instance");
		try {
			getHibernateTemplate().lock(instance, LockMode.NONE);
			log.debug("attach successful");
		} catch (RuntimeException re) {
			log.error("attach failed", re);
			throw re;
		}
	}

	public static SysUsersDAO getFromApplicationContext(ApplicationContext ctx) {
		return (SysUsersDAO) ctx.getBean("SysUsersDAO");
	}

}